/* License Notice:
**
** This program is free software: you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation, either version 3 of the License, or
**    (at your option) any later version.
** This program is distributed in the hope that it will be useful,
**   but WITHOUT ANY WARRANTY; without even the implied warranty of
**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
**   GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
**   along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

/**
 * @file font.hpp
 * @author TooOld2Rock'nRoll
 * @date 2025/02/27
 * @brief A class to handle the loading and processing of TrueType fonts for the ArcadeFighter library.
 *
 * @see https://github.com/nothings/stb
 * @see https://en.wikipedia.org/wiki/TrueType
 *
 * @bug We need to stop packing the bitmap atlas and go straight to the opengl texture buffer: https://github.com/arkanis/gl-4.5-subpixel-text-rendering/blob/main/main.c#L488
 * @todo How to handle a pack of multiple fonts in one file? Today we only create a Texture for the first one.
 * @todo How to preserve the space between characters in a font (like a monospace)? Today all chars will render optimally.
 */
#ifndef _FONT_HPP_
#define _FONT_HPP_

/*---- Includes ----*/
#include <map>

#include "texture.hpp"


/*---- Class Declaration ----*/
/**
 * @brief Processes TrueType fonts, creating a character atlas in the form of a Texture.
 * @extends Texture
 */
class Font : public Texture
{
    public:
        /** @brief Once loaded, this structure holds general information about the Font being used. */
        struct font_stats_s
        {
            size_t u_glyph_count = 0; ///<The number of glyph present in the font.

            float f_line_advance = 0.f; ///<How many pixels to increment the rendering position when advancing a line.
            float f_baseline = 0.f; ///<The Font baseline to render all glyph aligned as expected.
        };//end font_stats_s

        /**
         * @brief Each glyph in the font holds information critical to its correct rendering position in a sentence and
         *    in relation to each other.
         */
        struct glyph_stat_s
        {
            unsigned u_advance = 0; ///<The on screen space in pixels this character requires to be rendered.

            float f_xoff = 0.f; ///<The offset in x (from left) to keep the glyph aligned to each other (always >= 0).
            float f_yoff = 0.f; ///<The offset in y (from top) to keep the glyph aligned to the baseline (always >= 0).
        };//end glyph_stat_s

    private:
        std::map<unsigned, unsigned> m_codepoint2glyph; ///<It will be used to correlate the char in the label.

        //texture tile mapping
        Font::glyph_stat_s *pa_glyph_stats = nullptr;


    protected:
        using Texture::load;

        Font::font_stats_s st_font_statistics;///<Holds the font statistics.

    public:
        Font () : Texture () { }
        Font (const char *file_path, unsigned glyph_height);
        // ~Font ();

        virtual void load (const char *file_path, unsigned glyph_height);

        /** @brief Gets general statistics about this font. */
        const Font::font_stats_s& getStatistics () const { return this->st_font_statistics; }

        /** @brief Gets the glyph id (tile index) from a codepoint (char value). */
        unsigned getGlyphId (unsigned codepoint) { return this->m_codepoint2glyph.at (codepoint); }
        /** @brief Gets actual map of codepoints to glyph ids, to be used when rendering strings. */
        const std::map<unsigned, unsigned>& getCodepointList () { return this->m_codepoint2glyph; }


        /** @brief Gets the actual array of glyph statistics as processe don load.
         * @return <b>nullptr</b> if the Font was not processed yet, array of stats otherwise. */
        const Font::glyph_stat_s* getGlyphStatistics () const { return this->pa_glyph_stats; }
        const Font::glyph_stat_s& getGlyphStatistics (unsigned index) const;
};//END Font

#endif //_FONT_HPP_

